/* trackuino copyright (C) 2010  EA5HAV Javi
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "config.h"
#include "ax25.h"
#include "gps.h"
#include "aprs.h"
#include "sensors.h"
#include "modem.h"
#include <stdio.h>
#include <stdlib.h>
#include <WProgram.h>


//extern void *__bss_end;
//extern void *__brkval;


// Module globals
static unsigned int telemetry_counter = 0;
static unsigned int loss_of_gps_counter = 0;
static unsigned int ariss_counter = 0;

char old_lease[18];
// changed from const  
struct s_address addresses[] = { 
    {D_CALLSIGN, D_CALLSIGN_ID},  // Destination callsign
    {S_CALLSIGN, S_CALLSIGN_ID},  // Source callsign (-11 = balloon, -9 = car)
#ifdef DIGI_PATH1
    {DIGI_PATH1, DIGI_PATH1_TTL}, // Digi1 (first digi in the chain)
#endif
#ifdef DIGI_PATH2
    {DIGI_PATH2, DIGI_PATH2_TTL}, // Digi2 (second digi in the chain)
#endif
  };


// Module functions
float meters_to_feet(float m)
{
  // 10000 ft = 3048 m
  return m / 0.3048;
}


// Exported functions
void aprs_send()
{
  char temp[12];                   // Temperature (int/ext)
  unsigned long frequency;
 
// Send position packet only if we have a valid fix. Else only send telemetry.
  if(newPositionStillUnknown)
  {
    loss_of_gps_counter++;
    if(loss_of_gps_counter > 199) // make sure we don't get above 255 and still get the picture interpretable on the graph.
    {
      loss_of_gps_counter = 100; // will show a sawtooth pattern 100 -> 200 at permanent gps loss.
    }
  }
  else
  {
    loss_of_gps_counter = 0;
    ax25_send_header(addresses, sizeof(addresses)/sizeof(s_address));
    ax25_send_byte('/');                // Report w/ timestamp, no APRS messaging. $ = NMEA raw data
    // ax25_send_string("021709z");     // 021709z = 2nd day of the month, 17:09 zulu (UTC/GMT)
    ax25_send_string(gps_time);         // 170915 = 17h:09m:15s zulu (not allowed in Status Reports)
    ax25_send_byte('h');
    ax25_send_string(gps_aprs_lat);     // Lat: 38deg and 22.20 min (.20 are NOT seconds, but 1/100th of minutes)
    ax25_send_byte('/');                // Symbol table
    ax25_send_string(gps_aprs_lon);     // Lon: 000deg and 25.80 min
    ax25_send_byte('O');                // Symbol: O=balloon, -=QTH
    snprintf(temp, 4, "%03d", (int)(gps_course + 0.5)); 
    ax25_send_string(temp);             // Course (degrees)
    ax25_send_byte('/');                // and
    snprintf(temp, 4, "%03d", (int)(gps_speed + 0.5));
    ax25_send_string(temp);             // speed (knots)
    ax25_send_string("/A=");            // Altitude (feet). Goes anywhere in the comment area
    snprintf(temp, 7, "%06ld", (long)(meters_to_feet(gps_altitude) + 0.5));
    ax25_send_string(temp);
    ax25_send_string(" T=");
    ax25_send_string(itoa(sensors_lm335(), temp, 10));
    ax25_send_string("C/Ub=");
    ax25_send_string(itoa(getUBatt(), temp, 10));
    ax25_send_string("mV ");
    ax25_send_string(APRS_COMMENT);     // Comment
    ax25_send_footer();
    ax25_flush_frame();                 // Tell the modem to go
    strcpy(old_lease, gps_aprs_lat);
    strcat(old_lease, gps_aprs_lon);
    // Wait a few seconds
    delay(4000);
  }
  
  // Send a telemetry package
  ax25_send_header(addresses, sizeof(addresses)/sizeof(s_address));
  ax25_send_string("T#");                // Telemetry Report 
  telemetry_counter++;
  if (telemetry_counter > 999) {
    telemetry_counter = 0;
  }
  snprintf(temp, 4, "%03d", telemetry_counter);
  ax25_send_string(temp);              // sequential id
  ax25_send_byte(',');  

  digitalWrite(LM335_VS_PIN, HIGH); // Turn LM335 on (needed for temperature on adc2)
  for (int adc = 2; adc < 4; adc++) {  // adc2 = Ub, adc3 = LM335
    analogReference(DEFAULT);            
    analogRead(adc);            // Disregard the 1st conversion after changing ref
    int value = analogRead(adc);  // read ADC
    snprintf(temp, 4, "%03d", value/4L);  // Arduino has 1023 max.; APRS has 255 max.; So divide by 4
    ax25_send_string(temp);               // write 8 bit ADC value
    ax25_send_byte(',');  
  }
  digitalWrite(LM335_VS_PIN, LOW); // Turn LM335 off
  
  // fill the third telemetry value with a number that's proportional to the altitude:
  snprintf(temp, 4, "%03d", (long)(meters_to_feet(gps_altitude) + 0.5)/1000L); // Altitude in kfeet
  ax25_send_string(temp);               // write 8 bit value
  ax25_send_byte(',');  
  
  // fill the fourth telemetry value with the loss_of_gps_counter
  snprintf(temp, 4, "%03d", loss_of_gps_counter); 
  ax25_send_string(temp);               // write 8 bit value
  ax25_send_byte(',');   
  
  // fill the fifth telemetry value with the number of ARISS packets transmitted
  snprintf(temp, 4, "%03d", ariss_counter); 
  ax25_send_string(temp);               // write 8 bit value
  ax25_send_byte(',');   
  
  
  ax25_send_string("0000000"); // More room to send binary info. Still unused bits...
  if(satInView)
  {
    ax25_send_byte('1');
    ax25_send_byte(' ');
    frequency = MX146_FREQUENCY_ARISS;
    ariss_counter++;
    if(ariss_counter > 199) // prevent overflow but still produce interpretable graphs
    {
      ariss_counter = 100; // this will likely never happen :) However just in case...
    }
    
    addresses = { 
      {D_CALLSIGN, D_CALLSIGN_ID},  // Destination callsign still APRS
      {S_CALLSIGN, S_CALLSIGN_ID},  // Source callsign (-11 = balloon, -9 = car)
      {DIGI_PATH1_SAT, DIGI_PATH1_TTL_SAT}, // Digi1 = ARISS
      {DIGI_PATH2_SAT, DIGI_PATH2_TTL_SAT}, // Digi2 = SGATE
    };

  }
  else
  {
    ax25_send_byte('0');
    ax25_send_byte(' ');
    frequency = gps_get_region_frequency();
    
    addresses = { 
      {D_CALLSIGN, D_CALLSIGN_ID},  // Destination callsign changed back to normal
      {S_CALLSIGN, S_CALLSIGN_ID},  // Source callsign (-11 = balloon, -9 = car)
#ifdef DIGI_PATH1
      {DIGI_PATH1, DIGI_PATH1_TTL}, // Digi1 (first digi in the chain)
#endif
#ifdef DIGI_PATH2
      {DIGI_PATH2, DIGI_PATH2_TTL}, // Digi2 (second digi in the chain)
#endif
    };   

  }
  // Announce the next transmission
  snprintf(temp, 4, "%lu", frequency/1000000UL);  
  ax25_send_string(temp); 
  ax25_send_byte('.');
  snprintf(temp, 7, "%03lu", (frequency%1000000UL)/1000UL);  
  ax25_send_string(temp); 
  ax25_send_string("MHz next ISS:");     // Comment
  snprintf(temp, 7, "%d", iss_lat);
  ax25_send_string(temp);       // ISS lat
  ax25_send_byte('/');  
  snprintf(temp, 7, "%d", iss_lon);
  ax25_send_string(temp);       // ISS lon
//  ax25_send_byte('/'); 
//  snprintf(temp, 7, "%u", iss_datapoint);   
//  ax25_send_string(temp);
  
  if(newPositionStillUnknown) // append the last known position in case we lost GPS
  {
    ax25_send_string(" old:");     
    ax25_send_string(old_lease);
  }
  
// some output for debugging via packet:
// ax25_send_string(gps_date);         // 241211 = Christmas 2011

//  ax25_send_string(dtostrf(gps_get_variable(),7,4,temp)); 
//  ax25_send_byte('/');  
//  ax25_send_string(dtostrf(gps_get_lat(),7,4,temp)); 
//  ax25_send_byte('/');
//  ax25_send_string(dtostrf(gps_get_lon(),7,4,temp)); 
//  ax25_send_byte('/');
//  snprintf(temp, 7, "%lu", gps_get_time());   
//  ax25_send_string(temp);
//  ax25_send_byte('/');  
//  snprintf(temp, 7, "%lu", gps_get_date());   
//  ax25_send_string(temp);
//  snprintf(temp, 7, "%du", p13.Sx);   
//  ax25_send_string(temp);
  
  ax25_send_footer();
  ax25_flush_frame();                 // Tell the modem to go

  modem_set_tx_freq(frequency); // actually do the QSY
  
}


